﻿using AhpilyServer;
using PokerServer.Cache;
using PokerServer.Cache.Match;
using PokerServer.Model;
using Protocol.Code;
using Protocol.Dto;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace PokerServer.Logic
{
    public delegate void StartFight(List<int> uidList);

    public class MatchHandler : IHandler
    {
        public StartFight startFight;

        private readonly MatchCache matchCache = Caches.Match;
        private readonly UserCache userCache = Caches.User;

        public void OnDisconnect(ClientPeer client)
        {
            Leave(client);
        }

        public void OnReceive(ClientPeer client, int subCode, object value)
        {
            switch (subCode)
            {
                case MatchCode.ENTER_CREQ:
                    enter(client);
                    break;
                case MatchCode.LEAVE_CREQ:
                    Leave(client);
                    break;
                case MatchCode.READY_CREQ:
                    Ready(client);
                    break;
                default:
                    Console.WriteLine("Something wrong?");
                    break;
            }
        }


        #region 进入请求

        /// <summary>
        /// 进入
        /// </summary>
        /// <param name="client"></param>
        private void enter(ClientPeer client)
        {
            SingleExecute.Instance.Execute(
                delegate
                {
                    if (!userCache.IsOnline(client))
                    {
                        return;
                    }

                    int userId = userCache.GetId(client);
                    if (matchCache.IsMatching(userId))
                    {
                        // client.Send(OpCode.MATCH, MatchCode.ENTER_SRES, -1);    // 重复加入
                        return;
                    }

                    // 正常进入
                    MatchRoom room = matchCache.Enter(userId, client);


                    //广播给房间内除了当前客户端的其他用户，有新玩家计入了  参数：新进入的玩家的用户id

                    UserModel model = userCache.GetModelById(userId);
                    UserDto userDto = new UserDto(model.Id, model.Name, model.Bean, model.WinCount, model.LoseCount,
                        model.RunCount, model.Lv, model.Exp);


                    // 广播给其他人“来了老弟”
                    room.Brocast(OpCode.MATCH, MatchCode.ENTER_BRO, userDto, client);
                    // 返回恰当当前客户端 给他房间的数据模型
                    MatchRoomDto dto = makeRoomDto(room);

                    client.Send(OpCode.MATCH, MatchCode.ENTER_SRES, dto);
                    Console.WriteLine("老弟我来了");
                });
        }

        /// <summary>
        /// 根据服务器的匹配房间数据创建
        /// 给客户端的数据模型
        /// </summary>
        /// <param name="room"></param>
        /// <returns></returns>
        private MatchRoomDto makeRoomDto(MatchRoom room)
        {
            MatchRoomDto dto = new MatchRoomDto();
            foreach (var uid in room.UIdClientDict.Keys)
            {
                UserModel model = userCache.GetModelById(uid);

                UserDto userDto = new UserDto(model.Id, model.Name, model.Bean, model.WinCount, model.LoseCount,
                    model.RunCount, model.Lv, model.Exp);

                dto.UIdUserDict.Add(uid, userDto);

                dto.UIdList.Add(uid);
            }

            dto.ReadyUIdList = room.readyUIdList;

            return dto;
        }

        #region 离开请求

        /// <summary>
        /// 离开
        /// </summary>
        /// <param name="client"></param>
        private void Leave(ClientPeer client)
        {
            SingleExecute.Instance.Execute(
                delegate
                {
                    if (!userCache.IsOnline(client))
                    {
                        return;
                    }

                    int userId = userCache.GetId(client);

                    if (matchCache.IsMatching(userId) == false)
                    {
                        // 用户没有匹配 不能退出
                        // 非法操作
                        // client.Send(OpCode.MATCH, MatchCode.LEAVE_BRO, -1);
                        return;
                    }

                    // 正常离开
                    MatchRoom room = matchCache.Leave(userId);

                    // 老弟我走了
                    room.Brocast(OpCode.MATCH, MatchCode.LEAVE_BRO, userId);

                    Console.WriteLine("老弟我走了");
                });
        }

        #endregion

        /// <summary>
        /// 准备
        /// </summary>
        /// <param name="client"></param>
        private void Ready(ClientPeer client)
        {
            SingleExecute.Instance.Execute(
                delegate
                {
                    if (userCache.IsOnline(client) == false)
                    {
                        Debug.WriteLine("不该执行");
                        return;
                    }

                    int userId = userCache.GetId(client);

                    if (matchCache.IsMatching(userId) == false)
                    {
                        Debug.WriteLine("不该执行");
                        return;
                    }

                    MatchRoom room = matchCache.GetRoom(userId);

                    room.Ready(userId);
                    room.Brocast(OpCode.MATCH, MatchCode.READY_BRO, userId);

                    // 检查： 是否所有玩家都准备了
                    if (room.IsAllReady())
                    {
                        // 开始战斗
                        // 通知玩家 要进入战斗了
                        startFight(room.GetUiList());

                        room.Brocast(OpCode.MATCH, MatchCode.START_BRO, null);


                        // 清理房间
                        matchCache.Destroy(room);
                    }
                });
        }
    }
}

#endregion